import { Icon, useCommandManager } from '@amcax/base';
import i18n from 'i18next';
import { useEffect, useState } from 'react';
import { CircleButtonProps } from './types';

function describeArc(
  cx: number,
  cy: number,
  r1: number,
  r2: number,
  startAngle: number,
  endAngle: number,
) {
  // 角度转弧度
  const start = (angle: number, r: number) => ({
    x: cx + r * Math.cos(((angle - 90) * Math.PI) / 180),
    y: cy + r * Math.sin(((angle - 90) * Math.PI) / 180),
  });
  const p1 = start(startAngle, r2);
  const p2 = start(endAngle, r2);
  const p3 = start(endAngle, r1);
  const p4 = start(startAngle, r1);
  const largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
  return [
    `M ${p1.x} ${p1.y}`,
    `A ${r2} ${r2} 0 ${largeArcFlag} 1 ${p2.x} ${p2.y}`,
    `L ${p3.x} ${p3.y}`,
    `A ${r1} ${r1} 0 ${largeArcFlag} 0 ${p4.x} ${p4.y}`,
    'Z',
  ].join(' ');
}

export const CircleButton: React.FC<CircleButtonProps> = ({
  isEdit,
  onCmdInvoked,
  onCmdInvokFinished,
  activated,
  cmd,
  style,
  startAngle,
  endAngle,
  radius,
  innerRadius,
  iconSize = 18,
  onHoverLabelChange,
  onHoverLabelClear,
  onClick,
  onDragOver,
  onDragLeave,
  onDrop,
}) => {
  const { invokeCmd } = useCommandManager();
  const [disabled, setDisabled] = useState(!!cmd?.initialDisabled);
  const [hover, setHover] = useState(false);

  useEffect(() => {
    cmd?.subscribeDisabled?.(setDisabled);
  }, []);

  // 圆心
  const cx = radius;
  const cy = radius;

  // 图标中心角度
  const midAngle = (startAngle + endAngle) / 2;
  const iconR = (radius + innerRadius) / 2;
  const iconX =
    cx + iconR * Math.cos(((midAngle - 90) * Math.PI) / 180) - iconSize / 2;
  const iconY =
    cy + iconR * Math.sin(((midAngle - 90) * Math.PI) / 180) - iconSize / 2;

  // 颜色逻辑
  const fillColor = activated || hover ? '#cccccc' : '#ffffff90';
  const strokeColor = '#0000000f';

  const clickHandler = (e) => {
    if (isEdit) {
      return;
    }
    e.stopPropagation();
    e.preventDefault();
    if (!disabled && cmd) {
      invokeCmd(cmd, null, null, () => onCmdInvokFinished?.(cmd));
      onCmdInvoked?.(cmd);
    }
    onClick?.();
  };

  const contextMenuHandler = (e) => {
    if (isEdit) {
      return;
    }
    e.preventDefault();
    e.stopPropagation();
  };

  const mouseEnterHandler = () => {
    setHover(true);
    onHoverLabelChange?.(cmd?.label ? i18n.t(cmd?.label) : undefined);
  };

  const mouseLeaveHandler = () => {
    setHover(false);
    onHoverLabelClear?.();
  };

  const dragOverHandler = (e: React.DragEvent) => {
    e.preventDefault();
    mouseEnterHandler();
    onDragOver?.(cmd?.label);
  };

  const dragLeaveHandler = (e: React.DragEvent) => {
    e.preventDefault();
    mouseLeaveHandler();
    onDragLeave?.();
  };

  const dropHandler = (e: React.DragEvent) => {
    e.preventDefault();
    onDrop?.(e);
  };

  return (
    <svg
      width={radius * 2}
      height={radius * 2}
      style={{
        position: 'absolute',
        left: 0,
        top: 0,
        ...style,
        pointerEvents: 'none',
        zIndex: activated ? 10 : 2,
      }}
    >
      <path
        d={describeArc(cx, cy, innerRadius, radius, startAngle, endAngle)}
        fill={fillColor}
        stroke={strokeColor}
        strokeWidth={1}
        style={{
          cursor: disabled ? 'not-allowed' : 'pointer',
          transition: 'fill 0.2s, stroke 0.2s',
          pointerEvents: 'auto',
        }}
        onClick={clickHandler}
        onContextMenu={contextMenuHandler}
        onMouseEnter={mouseEnterHandler}
        onMouseLeave={mouseLeaveHandler}
        onDragOver={dragOverHandler}
        onDragLeave={dragLeaveHandler}
        onDrop={dropHandler}
      />
      <path
        d={describeArc(cx, cy, 0, innerRadius, startAngle, endAngle)}
        fill={'transparent'}
        stroke={'transparent'}
        strokeWidth={0}
        style={{
          cursor: disabled ? 'not-allowed' : 'pointer',
          transition: 'fill 0.2s, stroke 0.2s',
          pointerEvents: 'auto',
        }}
        onClick={clickHandler}
        onContextMenu={contextMenuHandler}
        onMouseEnter={mouseEnterHandler}
        onMouseLeave={mouseLeaveHandler}
        onDragOver={dragOverHandler}
        onDragLeave={dragLeaveHandler}
        onDrop={dropHandler}
      />
      <g style={{ pointerEvents: 'none' }}>
        {cmd?.icon && (
          <foreignObject
            x={iconX}
            y={iconY}
            width={iconSize}
            height={iconSize}
          >
            <div
              style={{
                width: iconSize,
                height: iconSize,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              <Icon
                name={cmd?.icon}
                style={{ fontSize: iconSize, opacity: disabled ? 0.3 : 1 }}
              />
            </div>
          </foreignObject>
        )}
      </g>
    </svg>
  );
};
